home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
csrc1.arc
/
OBJREF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-07-27
|
7KB
|
392 lines
/*
* O B J R E F
*
* NOTE: this program has been superceded by additional capabilities in
* nm.c (in tools). It is included here as it offers a simple set of
* subroutines for processing symbol tables.
*/
/*)BUILD $(TKBOPTIONS) = {
TASK = ...REF
}
*/
#ifdef DOCUMENTATION
title objref Object file cross reference
index Object file cross reference
synopsis
objref file_list
description
objref reads each file in the list, building a cross reference
listing of symbols (where symbols were defined and referenced).
.s
The files in the file_list were output by nm. The file_list
arguments may contain wildcards. The argument string to nm
is as follows:
.s
nm "-1" file.obj >file.nm
author
Martin Minow
bugs
Superceded by additional capabilities in nm.c
#endif
#include <stdio.h>
#define FALSE 0
#define TRUE 1
#define EOS 0
typedef struct symbol {
struct symbol *s_next;
char *s_name;
struct module *s_defn; /* Where it's defined */
struct refer *s_refer; /* Where it's referenced */
} SYMBOL;
typedef struct module {
struct module *m_next;
char *m_name;
int m_index;
} MODULE;
typedef struct refer {
struct refer *r_next;
struct module *r_module;
} REFERENCE;
SYMBOL *sfirst = NULL;
MODULE *mfirst = NULL;
REFERENCE *rfirst = NULL;
FILE *fd;
char line[133];
char name[133];
char value[133];
#define CROSS_MAX 25
int cross[CROSS_MAX][CROSS_MAX];
char *mname[CROSS_MAX];
int cmax = -1;
extern char *strsave();
extern char *myalloc();
main(argc, argv)
int argc;
char *argv[];
{
register int nfiles;
register int i;
for (i = 1; i < argc; i++) {
if ((fd = fwild(argv[i], "r")) == NULL) {
fprintf(stderr, "can't open wild card file: ");
perror(argv[i]);
continue;
}
for (nfiles = 0; fnext(fd) != NULL; nfiles++) {
process();
}
if (nfiles == 0) {
fprintf(stderr, "no files match \"%s\"\n", argv[i]);
}
}
mnames();
output();
}
process()
/*
* For each file ...
*/
{
register MODULE *mp;
register SYMBOL *sy;
extern MODULE *newmodule();
extern SYMBOL *lookup();
getfilename(fd, line);
mp = newmodule(line);
while (fgets(line, sizeof line, fd) != NULL) {
sscanf(line, "%s%*s%s", &name, &value);
sy = lookup(name);
if (value[0] == '*') {
addref(sy, mp); /* Undefined here */
}
else { /* Defined here */
if (sy->s_defn != NULL) {
printf("** symbol %s defined in %s and %s\n",
sy->s_name, (sy->s_defn)->m_name,
mp->m_name);
fprintf(stderr,
"** symbol %s defined in %s and %s\n",
sy->s_name, (sy->s_defn)->m_name,
mp->m_name);
}
else {
sy->s_defn = mp;
}
}
}
}
output()
{
register SYMBOL *sy;
register int nsy;
register REFERENCE *rp;
int i, j;
/*
* Pass 1 for "library" symbols only
*/
printf("The following are not defined:\n");
nsy = 0;
for (sy = sfirst; sy != NULL; sy = sy->s_next) {
if (sy->s_defn == NULL) {
printf("%c%s",
((nsy & 7) == 0) ? '\n' : '\t', sy->s_name);
nsy++;
}
}
printf("\n\n");
/*
* Pass 2 for symbols not used elsewhere
*/
printf("The following are not used outside of their module:\n");
nsy = 0;
for (sy = sfirst; sy != NULL; sy = sy->s_next) {
if (sy->s_defn != NULL && sy->s_refer == NULL) {
printf("%c%s\t%s",
((nsy & 3) == 0) ? '\n' : '\t',
sy->s_name, (sy->s_defn)->m_name);
nsy++;
}
}
/*
* Pass 3 -- all the rest
*/
printf("\n\nThe following are defined and used elsewhere\n");
for (sy = sfirst; sy != NULL; sy = sy->s_next) {
if (sy->s_defn == NULL || sy->s_refer == NULL) {
continue;
}
i = (sy->s_defn)->m_index;
printf("\n%s\t%s:", sy->s_name, (sy->s_defn)->m_name);
nsy = 0;
for (rp = sy->s_refer; rp != NULL; rp = rp->r_next) {
printf("%s%s",
((++nsy % 6) == 0) ? "\n\t\t" : "\t",
(rp->r_module)->m_name);
j = (rp->r_module)->m_index;
cross[i][j]++;
}
}
printf("\n");
/*
* Now for the map
*/
printf("\nmodule");
for (i = 0; i <= cmax; i++) {
printf("\n%s\t", mname[i]);
for (j = 0; j < i; j++) {
printf("%4d", cross[i][j] + cross[j][i]);
}
printf(" %s", mname[i]);
}
}
/*
* Manage symbol table
*/
MODULE *
newmodule(text)
/*
* Make this a new module entry.
*/
{
register MODULE *mp;
register MODULE **mplast;
register MODULE *new;
int i;
new = myalloc(sizeof (MODULE));
new->m_name = strsave(text);
for (mplast = &mfirst; (mp = *mplast) != NULL; mplast = &mp->m_next) {
if ((i = strcmp(text, mp->m_name)) < 0)
break;
else if (i == 0) {
fprintf(stderr, "duplicate module name \"%s\"\n",
text);
return(mp);
}
}
new->m_next = mp;
*mplast = new;
cmax++;
if (cmax >= CROSS_MAX)
error("too many modules");
return(new);
}
addref(sy, mp)
SYMBOL *sy;
MODULE *mp;
/*
* The module references this symbol.
*/
{
register REFERENCE *rp;
REFERENCE **rplast;
register REFERENCE *new;
register int i;
new = myalloc(sizeof (REFERENCE));
new->r_module = mp;
for (rplast = &sy->s_refer;
(rp = *rplast) != NULL;
rplast = &rp->r_next) {
if ((i = strcmp(mp->m_name, (rp->r_module)->m_name)) == 0) {
fprintf(stderr, "\"%s\" references \"%s\" twice\n",
sy->s_name, mp->m_name);
}
else if (i < 0) {
break;
}
}
new->r_next = rp;
*rplast = new;
}
SYMBOL *
lookup(text)
char *text;
/*
* Return pointer to this symbol, insert if new
*/
{
register SYMBOL *sy;
SYMBOL **sylast;
register SYMBOL *new;
register int i;
for (sylast = &sfirst; (sy = *sylast) != NULL; sylast = &sy->s_next) {
if ((i = strcmp(text, sy->s_name)) == 0) {
return(sy);
}
else if (i < 0) {
break;
}
}
new = myalloc(sizeof (SYMBOL));
new->s_name = strsave(text);
new->s_next = sy;
*sylast = new;
return (new);
}
mnames()
/*
* Build mname[] vector
*/
{
register int i;
register MODULE *mp;
i = 0;
for (mp = mfirst; mp != NULL; mp = mp->m_next, i++) {
mname[i] = mp->m_name;
mp->m_index = i;
}
}
/*
* Support routines
*/
getfilename(filedes, buffer)
FILE *filedes;
char *buffer;
{
register char *tp;
register char c;
fgetname(filedes, buffer);
/*
* Skip over device name
*/
for (tp = buffer; (c = *tp) != EOS && c != ':'; tp++);
if (c) tp++;
else tp = buffer;
/*
* Skip over [UIC] or
* or [PPN] if present
*/
if (*tp == '[' || *tp == '(') {
while ((c = *tp++)
&& c != ']'
&& c != ')');
if (c == 0) {
error("Can't happen");
tp--;
}
}
strcpy(buffer, tp);
/*
* Don't include version
*/
for (tp = buffer; (c = *tp) && c != ';'; tp++);
*tp = 0;
/*
* Don't include .ext
*/
for (tp = buffer; (c = *tp) && c != '.'; tp++);
*tp = 0;
/*
* Now, buffer has the file name,
* tp - buffer, its length.
*/
return(buffer);
}
char *
strsave(text)
char *text;
/*
* Save this text
*/
{
register char *p;
if ((p = malloc(strlen(text) + 1)) == NULL)
error("No room for string alloc.");
strcpy(p, text);
return (p);
}
char *
myalloc(size)
int size;
/*
* Allocate or die
*/
{
register char *p;
if ((p = calloc(1, size)) == NULL) {
fprintf(stderr, "Can't allocate %d bytes\n", size);
error("Fatal");
}
return (p);
}